# Required packages for our course. Do not delete.
library(tidyverse)
library(mosaic)

Big-picture

Research Question

How did Kobe Bryant’s scoring and overall performance metrics (such as assists, rebounds, and points) evolve throughout his career?

This question aims to explore the trajectory of Kobe Bryant’s performance over his NBA career, highlighting his development and consistency as a player. Through visualization, I hope to illustrate not just his scoring ability, which he is widely renowned for, but also how his contributions in other aspects of the game changed over time. This could provide insights into his adaptability, growth as a player, and how his role within the Los Angeles Lakers evolved. By analyzing the patterns and trends in his performance metrics across different seasons, we can appreciate the breadth of his impact on basketball.


Data

Description of data

The dataset comprises detailed game-by-game statistics of Kobe Bryant’s NBA career, focusing on various performance metrics such as points scored, assists, rebounds, steals, blocks, turnovers, and personal fouls, among others. It includes data from each game, specifying the date, Kobe’s age at the time of the game, the team played for (Los Angeles Lakers), whether it was a regular season or playoff game, the game’s venue, the opponent team, and the game’s outcome in terms of win or loss and point difference. Additional details include whether Kobe started the game, minutes played, and shooting efficiency (field goals, three-pointers, and free throws).

Load data into R

Include the code to load your data here. Using the head() function, show the first 10 rows of data.

file_path <- "C:/Users/shrir/OneDrive/Desktop/kobebryant.csv"

# Load the dataset
kobe_bryant <- read.csv(file_path, header = TRUE, stringsAsFactors = FALSE)

# Display the first 10 rows using the head() function
head(kobe_bryant, 10)
season date age team_played game_type venue opponent win_lose point_difference game_started minutes_played fieldgoal fieldgoal_attempts fieldgoal_percent X3pointers X3pointers_attempts X3pointers_percent freethrows freethrows_attempt freethrow_percent offensive_rebounds defensive_rebounds total_rebounds assists steals blocks turnovers personal_fouls points
1 11/1/1996 18 los angeles lakers season away phoenix suns w 14 Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null Null
1 11/3/1996 18 los angeles lakers season away minnesota timberwolves w 6 0 6:22 0 1 0 0 0 0 0 0 1 1 0 0 1 1 1 0
1 11/5/1996 18 los angeles lakers season home new york knicks w 6 0 3:16 0 1 0 0 0 1 2 0.5 0 0 0 0 0 0 1 0 1
1 11/6/1996 18 los angeles lakers season home charlotte hornets l -10 0 6:49 2 3 0.667 1 2 0.5 0 0 0 0 0 0 0 0 3 0 5
1 11/8/1996 18 los angeles lakers season home toronto rapters l -1 0 17:15 3 8 0.375 2 3 0.667 2 4 0.5 0 3 3 0 0 1 0 3 10
1 11/10/1996 18 los angeles lakers season away atlanta hawks w 7 0 8:25 0 3 0 0 0 2 2 1 1 2 3 1 0 0 0 0 2
1 11/12/1996 18 los angeles lakers season home houston rockets w 11 0 5:03 1 2 0.5 0 1 0 0 0 0 1 1 0 0 0 2 0 2
1 11/13/1996 18 los angeles lakers season home san antonio spurs l -12 0 6:06 2 2 1 1 1 1 1 1 1 0 0 0 0 1 0 0 2 6
1 11/15/1996 18 los angeles lakers season away los angeles clippers w 7 0 7:01 1 4 0.25 0 2 0 2 3 0.667 0 0 0 0 0 0 1 4 4
1 11/17/1996 18 los angeles lakers season home phoenix suns w 14 0 14:29 5 8 0.625 4 6 0.667 2 2 1 2 0 2 2 0 0 4 2 16

Variables

Using the names() function, show the names of all the columns (i.e. potential variables) in your data set. Delete this when complete.

names(kobe_bryant)
##  [1] "season"              "date"                "age"                
##  [4] "team_played"         "game_type"           "venue"              
##  [7] "opponent"            "win_lose"            "point_difference"   
## [10] "game_started"        "minutes_played"      "fieldgoal"          
## [13] "fieldgoal_attempts"  "fieldgoal_percent"   "X3pointers"         
## [16] "X3pointers_attempts" "X3pointers_percent"  "freethrows"         
## [19] "freethrows_attempt"  "freethrow_percent"   "offensive_rebounds" 
## [22] "defensive_rebounds"  "total_rebounds"      "assists"            
## [25] "steals"              "blocks"              "turnovers"          
## [28] "personal_fouls"      "points"

The variables I used in my data visualization design are:

#season - To analyze performance across different seasons.

#points - For insights on scoring trends.

#game_type - To distinguish between regular season and playoff performances.

#win_lose - To correlate Kobe’s performance with team success.

#fieldgoal_percent - To evaluate shooting efficiency over time.


Data Analysis

Summary Statistics

Using the favstats() function, calculate the necessary statistics you used to create your data visualization. Delete this when complete.

# Convert necessary columns to numeric, handling non-numeric entries
kobe_bryant$points <- as.numeric(as.character(kobe_bryant$points))

# Calculate favorite statistics for points
points_stats <- favstats(~ points, data = kobe_bryant)

print(points_stats)
##  min Q1 median Q3 max    mean       sd    n missing
##    0 18     25 32  81 25.0869 10.60878 1565     212

Provide the high-level insights you used to craft your data visualization design.

Additional Analyses

If you conducted any other analyses of your data set to gather the data in your project, use this section to conduct your research. Delete this when complete.

Opening Timeline of Career Highlights

library(ggplot2)
library(plotly)
library(dplyr)


# Convert factors to characters to ensure they work well with plotly
kobe_bryant$season <- as.character(kobe_bryant$season)

# Ensure 'points' is numeric for calculations
kobe_bryant$points <- as.numeric(as.character(kobe_bryant$points))

# Calculate average points per season
avg_points_per_season <- kobe_bryant %>%
  group_by(season) %>%
  summarise(avg_points = mean(points, na.rm = TRUE))

# Create the ggplot
p <- ggplot(avg_points_per_season, aes(x = season, y = avg_points)) +
  geom_line() +
  geom_point() +
  theme_minimal() +
  labs(title = "Kobe Bryant's Average Points per Season",
       x = "Season",
       y = "Average Points")

# Convert ggplot to an interactive plotly object
interactive_p <- ggplotly(p)

# Print the interactive plot to the Viewer in RStudio or in your R environment
print(interactive_p)
library(ggplot2)
library(plotly)

# Find the top scoring games
top_scoring_games <- kobe_bryant %>%
  arrange(desc(points)) %>%
  top_n(10, points)

# Plot
top_games_plot <- ggplot(top_scoring_games, aes(x = reorder(date, points), y = points)) +
  geom_col() +
  coord_flip() +
  labs(title = "Top 10 Scoring Games of Kobe Bryant's Career",
       x = "Date of Game", y = "Points Scored") +
  theme_minimal()

# Make interactive
top_games_interactive <- ggplotly(top_games_plot)
top_games_interactive
# Calculate average points per season
seasonal_points <- kobe_bryant %>%
  group_by(season) %>%
  summarise(avg_points = mean(points, na.rm = TRUE))

# Plot
seasonal_points_plot <- ggplot(seasonal_points, aes(x = season, y = avg_points)) +
  geom_line() +
  geom_point() +
  labs(title = "Seasonal Scoring Consistency Over Kobe Bryant's Career",
       x = "Season", y = "Average Points per Game") +
  theme_minimal()

# Make interactive
seasonal_points_interactive <- ggplotly(seasonal_points_plot)
seasonal_points_interactive
clutch_performances <- kobe_bryant %>%
  filter(point_difference <= 5, minutes_played >= '00:45:00') %>%
  mutate(final_minutes_points = as.numeric(points))

plot_ly(clutch_performances, x = ~season, y = ~final_minutes_points, type = 'scatter', mode = 'markers') %>%
  layout(title = "Kobe Bryant's Clutch Performances", xaxis = list(title = "Season"), yaxis = list(title = "Points in Final Minutes"))
library(ggplot2)
library(plotly)

# Example data frame with milestones
milestones <- data.frame(
  year = c(1996, 2000, 2006, 2010, 2016),
  event = c("NBA Debut", "1st Championship", "81 Points Game", "5th Championship", "Retirement"),
  y = rep(1, 5) # Same y level for all points, you can adjust this for better positioning
)

# Plotting the timeline
milestone_plot <- ggplot(milestones, aes(x = year, y = y, label = event)) +
  geom_line(aes(group = 1)) + # One group for all points
  geom_point() + # Add points to the timeline
  geom_text(nudge_y = 0.1) + # Slightly nudge text above the points
  labs(title = "Kobe Bryant's Career Milestones",
       x = "Year",
       y = "") + # Remove y-axis label
  theme_minimal() +
  theme(axis.line.y = element_blank(), # Remove y-axis line
        axis.text.y = element_blank(), # Remove y-axis text
        axis.ticks.y = element_blank()) # Remove y-axis ticks

# Making it interactive
interactive_milestone_plot <- ggplotly(milestone_plot)

# Save the interactive plot if needed
htmlwidgets::saveWidget(interactive_milestone_plot, "milestone_plot.html")
library(ggplot2)
library(dplyr)
library(plotly)

# Assuming 'points' and 'opponent' are in your dataset and 'season' is in the format 'YYYY-YY'
scoring_heatmap_data <- kobe_bryant %>%
  group_by(season, opponent) %>%
  summarise(avg_points = mean(points, na.rm = TRUE), .groups = 'drop') %>%
  arrange(opponent, season)

p <- ggplot(scoring_heatmap_data, aes(x = season, y = reorder(opponent, -avg_points), fill = avg_points)) +
  geom_tile() +
  scale_fill_gradient(low = "blue", high = "red") +
  labs(title = "Kobe Bryant's Average Points Per Game Across Seasons",
       x = "Season",
       y = "Opponent") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

# Make it interactive
ggplotly(p)
# Histogram of Kobe's points
p5 <- ggplot(kobe_bryant, aes(x = points)) +
  geom_histogram(binwidth = 5, fill = "blue", color = "white") +
  theme_minimal() +
  labs(title = "Kobe Bryant's Career Points Distribution", x = "Points", y = "Frequency")

ggplotly(p5)
library(ggplot2)
library(plotly)
library(dplyr)

# Ensure 'points' is numeric
kobe_bryant$points <- as.numeric(as.character(kobe_bryant$points))

# Filter data for early years and calculate average points per season
early_years <- kobe_bryant %>%
  mutate(season = as.character(season)) %>%  # Convert season to character if it's not
  filter(season <= "1999-00") %>%
  group_by(season) %>%
  summarise(avg_points = mean(points, na.rm = TRUE))

# Plotting
p <- ggplot(early_years, aes(x = season, y = avg_points)) +
  geom_line() +
  geom_point() +
  labs(title = "Kobe's Rise to Stardom: Points Per Game in Early Seasons",
       x = "Season",
       y = "Average Points") +
  theme_minimal()

ggplotly(p)
# Convert assists to numeric
kobe_bryant$assists <- as.numeric(as.character(kobe_bryant$assists))

# Create a summary of average assists against each opponent
assist_heatmap_data <- kobe_bryant %>%
  group_by(opponent) %>%
  summarise(avg_assists = mean(assists, na.rm = TRUE)) %>%
  arrange(desc(avg_assists))

# Create the heatmap
p <- ggplot(assist_heatmap_data, aes(x = reorder(opponent, -avg_assists), y = avg_assists)) +
  geom_tile(aes(fill = avg_assists)) + 
  scale_fill_gradient(low = "blue", high = "red") +
  labs(title = "Kobe Bryant's Average Assists Against Each Opponent",
       x = "Opponent",
       y = "Average Assists") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Convert to interactive plot
interactive_heatmap <- ggplotly(p)

# Save the interactive plot as HTML
htmlwidgets::saveWidget(interactive_heatmap, 'kobe_assists_heatmap.html', selfcontained = TRUE)

# Convert points to numeric if it's not already
kobe_bryant$points <- as.numeric(as.character(kobe_bryant$points))

# Identify the peak performances
peak_performances <- kobe_bryant %>%
  arrange(desc(points)) %>%
  select(season, date, opponent, points) %>%
  head(n = 10) # You can change 'n' to see more or fewer performances

# Display the table
print(peak_performances)
##    season       date              opponent points
## 1      10  1/22/2006       toronto rapters     81
## 2      11  3/16/2007 portland trailbrazers     65
## 3      10 12/20/2005      dallas mavericks     62
## 4      13   2/2/2009       new york knicks     61
## 5      11  3/22/2007     memphis grizzlies     60
## 6      20  4/13/2016             utah jazz     60
## 7      11 12/29/2006     charlotte hornets     58
## 8       6  1/14/2002     memphis grizzlies     56
## 9       7  3/28/2003    washington wizards     55
## 10     11 12/15/2006       houston rockets     53
# Ensure the necessary columns are numeric
kobe_bryant$points <- as.numeric(as.character(kobe_bryant$points))
kobe_bryant$assists <- as.numeric(as.character(kobe_bryant$assists))
kobe_bryant$total_rebounds <- as.numeric(as.character(kobe_bryant$total_rebounds))

# Calculate a simple 'Performance Score' for each game
kobe_bryant <- kobe_bryant %>%
  mutate(performance_score = points + assists + total_rebounds)

# Find the top performances based on this score
top_performances <- kobe_bryant %>%
  arrange(desc(performance_score)) %>%
  select(season, date, opponent, points, assists, total_rebounds, performance_score) %>%
  head(n = 10) # Adjust 'n' to show more or fewer performances

# Display the table
print(top_performances)
##    season       date              opponent points assists total_rebounds
## 1      10  1/22/2006       toronto rapters     81       2              6
## 2      11  3/16/2007 portland trailbrazers     65       3              7
## 3      11 12/15/2006       houston rockets     53       8             10
## 4      10 12/20/2005      dallas mavericks     62       0              8
## 5      11  3/22/2007     memphis grizzlies     60       4              5
## 6      20  4/13/2016             utah jazz     60       4              4
## 7       5  5/13/2001      sacramento kings     48       3             16
## 8       7  2/18/2003       houston rockets     52       7              8
## 9      11 12/29/2006     charlotte hornets     58       4              5
## 10     12   3/2/2008      dallas mavericks     52       4             11
##    performance_score
## 1                 89
## 2                 75
## 3                 71
## 4                 70
## 5                 69
## 6                 68
## 7                 67
## 8                 67
## 9                 67
## 10                67

Interactive Presentation or Website Visualiztion

Module 3’s Project allows students to choose ONE OPTION among the two options provided below. You should denote which ONE of the two options you plan to pursue and provide a brief overview of your vision for the project. Delete the other options that you will not be pursuing.

Option 2 | Interactive Website

Students will create a website that present their data findings and topic in a website where users can engage with their platform. Students must include a minimum of 5 pages of analysis, 1 page for their home, and 1 page for references/overview.

  • Website Softwares Students are Allowed to Use:
    • Google Sites (Free!)

Link of my webpage

https://sites.google.com/view/kobe-bryant-insh5302/home?authuser=0

Page 1: Kobe’s Inception: The Making of a Legend This page delves into the formative years of Kobe Bryant’s career, examining how a young, ambitious athlete evolved into a future icon of basketball. Through interactive visualizations of his early performance, visitors can trace the steady climb of his skills and achievements, setting the foundation for a storied career.

Page 2: Dominance in Scoring Here we explore Kobe’s reputation as a scoring powerhouse. The data vividly illustrates his ability to consistently rack up points, regardless of the opponent or season. Interactive charts allow users to see just how Kobe’s scoring prowess made him one of the most feared offensive players in the NBA.

Page 3: Kobe - A Team Man! Moving beyond individual accolades, this page focuses on Kobe’s contributions to team success. With visualizations highlighting his assists and rebounds, we celebrate Kobe not just as a scorer, but as a true team player who elevated those around him through selfless play and strategic assists.

Page 4: Clutch Scoring: Kobe’s Playoff Dominance Kobe’s ability to perform under pressure is legendary, and this page’s interactive visualizations showcase his elevated game during playoffs. By examining his clutch scoring when it mattered most, this page illustrates how Kobe became synonymous with the term ‘clutch,’ solidifying his role as a pivotal player in crucial moments.

Page 5: Kobe’s Legacy The final page is a tribute to the enduring legacy of Kobe Bryant. It encapsulates his career through interactive timelines and milestone charts that narrate the story of a relentless competitor, an inspiring leader, and a cultural icon whose influence transcended the sport itself.

For each page, the data visualizations not only serve as evidence of Kobe’s basketball prowess but also as narrative tools that allow visitors to engage with his journey and understand the depth of his impact on the sport.


References

Kobe Bryant References >“Kobe Bryant Biography & Facts,” Biography.com, available at biography.com/athletes/kobe-bryant.

“Kobe Bryant’s Life, Lakers Career & Legacy,” Lakers Nation, available at lakersnation.com/kobe-bryant-biography-life-lakers-career-and-legacy.

“Exploring Kobe Bryant’s NBA Journey,” Kaggle dataset by Alfred Kondoro, available at kaggle.com/datasets/alfredkondoro/exploring-kobe-bryants-nba-journey.

Various images and information sourced from Google Images and Medium Data Science articles, with credits given to the photographers and authors where available.


All done!

Knit the completed R Markdown file as a HTML document (click the “Knit” button at the top of the script editor window) and upload it to the submission portal on Canvas.

LS0tDQp0aXRsZTogIk1vZHVsZSAzIFByb2plY3QgMzogUHJlc2VudGF0aW9uIG9yIFdlYnNpdGUgVmlzdWFsaXphdGlvbiBBc3NpZ25tZW50Ig0Kc3VidGl0bGU6ICJJTlNIIDUzMDIgLSAgSW5mb3JtYXRpb24gRGVzaWduICYgVmlzdWFsIEFuYWx5dGljcyINCmF1dGhvcjogIlNocmlyYW0gVmlqYXlrdW1hciINCmRhdGU6ICJBcHIgNywgMjAyNCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAyDQogICAgZGZfcHJpbnQ6IGthYmxlDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KLS0tDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KIyBSZXF1aXJlZCBwYWNrYWdlcyBmb3Igb3VyIGNvdXJzZS4gRG8gbm90IGRlbGV0ZS4NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShtb3NhaWMpDQpgYGANCg0KIyBCaWctcGljdHVyZQ0KDQojIyBSZXNlYXJjaCBRdWVzdGlvbg0KDQo+IEhvdyBkaWQgS29iZSBCcnlhbnQncyBzY29yaW5nIGFuZCBvdmVyYWxsIHBlcmZvcm1hbmNlIG1ldHJpY3MgKHN1Y2ggYXMgYXNzaXN0cywgcmVib3VuZHMsIGFuZCBwb2ludHMpIGV2b2x2ZSB0aHJvdWdob3V0IGhpcyBjYXJlZXI/DQoNCj4gVGhpcyBxdWVzdGlvbiBhaW1zIHRvIGV4cGxvcmUgdGhlIHRyYWplY3Rvcnkgb2YgS29iZSBCcnlhbnQncyBwZXJmb3JtYW5jZSBvdmVyIGhpcyBOQkEgY2FyZWVyLCBoaWdobGlnaHRpbmcgaGlzIGRldmVsb3BtZW50IGFuZCBjb25zaXN0ZW5jeSBhcyBhIHBsYXllci4gVGhyb3VnaCB2aXN1YWxpemF0aW9uLCBJIGhvcGUgdG8gaWxsdXN0cmF0ZSBub3QganVzdCBoaXMgc2NvcmluZyBhYmlsaXR5LCB3aGljaCBoZSBpcyB3aWRlbHkgcmVub3duZWQgZm9yLCBidXQgYWxzbyBob3cgaGlzIGNvbnRyaWJ1dGlvbnMgaW4gb3RoZXIgYXNwZWN0cyBvZiB0aGUgZ2FtZSBjaGFuZ2VkIG92ZXIgdGltZS4gVGhpcyBjb3VsZCBwcm92aWRlIGluc2lnaHRzIGludG8gaGlzIGFkYXB0YWJpbGl0eSwgZ3Jvd3RoIGFzIGEgcGxheWVyLCBhbmQgaG93IGhpcyByb2xlIHdpdGhpbiB0aGUgTG9zIEFuZ2VsZXMgTGFrZXJzIGV2b2x2ZWQuIEJ5IGFuYWx5emluZyB0aGUgcGF0dGVybnMgYW5kIHRyZW5kcyBpbiBoaXMgcGVyZm9ybWFuY2UgbWV0cmljcyBhY3Jvc3MgZGlmZmVyZW50IHNlYXNvbnMsIHdlIGNhbiBhcHByZWNpYXRlIHRoZSBicmVhZHRoIG9mIGhpcyBpbXBhY3Qgb24gYmFza2V0YmFsbC4NCg0KKiAqICoNCg0KIyBEYXRhDQoNCiMjIERlc2NyaXB0aW9uIG9mIGRhdGENCg0KPiBUaGUgZGF0YXNldCBjb21wcmlzZXMgZGV0YWlsZWQgZ2FtZS1ieS1nYW1lIHN0YXRpc3RpY3Mgb2YgS29iZSBCcnlhbnQncyBOQkEgY2FyZWVyLCBmb2N1c2luZyBvbiB2YXJpb3VzIHBlcmZvcm1hbmNlIG1ldHJpY3Mgc3VjaCBhcyBwb2ludHMgc2NvcmVkLCBhc3Npc3RzLCByZWJvdW5kcywgc3RlYWxzLCBibG9ja3MsIHR1cm5vdmVycywgYW5kIHBlcnNvbmFsIGZvdWxzLCBhbW9uZyBvdGhlcnMuIEl0IGluY2x1ZGVzIGRhdGEgZnJvbSBlYWNoIGdhbWUsIHNwZWNpZnlpbmcgdGhlIGRhdGUsIEtvYmUncyBhZ2UgYXQgdGhlIHRpbWUgb2YgdGhlIGdhbWUsIHRoZSB0ZWFtIHBsYXllZCBmb3IgKExvcyBBbmdlbGVzIExha2VycyksIHdoZXRoZXIgaXQgd2FzIGEgcmVndWxhciBzZWFzb24gb3IgcGxheW9mZiBnYW1lLCB0aGUgZ2FtZSdzIHZlbnVlLCB0aGUgb3Bwb25lbnQgdGVhbSwgYW5kIHRoZSBnYW1lJ3Mgb3V0Y29tZSBpbiB0ZXJtcyBvZiB3aW4gb3IgbG9zcyBhbmQgcG9pbnQgZGlmZmVyZW5jZS4gQWRkaXRpb25hbCBkZXRhaWxzIGluY2x1ZGUgd2hldGhlciBLb2JlIHN0YXJ0ZWQgdGhlIGdhbWUsIG1pbnV0ZXMgcGxheWVkLCBhbmQgc2hvb3RpbmcgZWZmaWNpZW5jeSAoZmllbGQgZ29hbHMsIHRocmVlLXBvaW50ZXJzLCBhbmQgZnJlZSB0aHJvd3MpLg0KDQoNCiMjIExvYWQgZGF0YSBpbnRvIFINCg0KKkluY2x1ZGUgdGhlIGNvZGUgdG8gbG9hZCB5b3VyIGRhdGEgaGVyZS4gVXNpbmcgdGhlIGhlYWQoKSBmdW5jdGlvbiwgc2hvdyB0aGUgZmlyc3QgMTAgcm93cyBvZiBkYXRhLiAqDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KZmlsZV9wYXRoIDwtICJDOi9Vc2Vycy9zaHJpci9PbmVEcml2ZS9EZXNrdG9wL2tvYmVicnlhbnQuY3N2Ig0KDQojIExvYWQgdGhlIGRhdGFzZXQNCmtvYmVfYnJ5YW50IDwtIHJlYWQuY3N2KGZpbGVfcGF0aCwgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQojIERpc3BsYXkgdGhlIGZpcnN0IDEwIHJvd3MgdXNpbmcgdGhlIGhlYWQoKSBmdW5jdGlvbg0KaGVhZChrb2JlX2JyeWFudCwgMTApDQoNCmBgYA0KDQoqICogKg0KDQojIFZhcmlhYmxlcw0KDQoqVXNpbmcgdGhlIG5hbWVzKCkgZnVuY3Rpb24sIHNob3cgdGhlIG5hbWVzIG9mIGFsbCB0aGUgY29sdW1ucyAoaS5lLiBwb3RlbnRpYWwgdmFyaWFibGVzKSBpbiB5b3VyIGRhdGEgc2V0LiBEZWxldGUgdGhpcyB3aGVuIGNvbXBsZXRlLioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbmFtZXMoa29iZV9icnlhbnQpDQoNCmBgYA0KDQo+IFRoZSB2YXJpYWJsZXMgSSB1c2VkIGluIG15IGRhdGEgdmlzdWFsaXphdGlvbiBkZXNpZ24gYXJlOg0KDQojc2Vhc29uIC0gVG8gYW5hbHl6ZSBwZXJmb3JtYW5jZSBhY3Jvc3MgZGlmZmVyZW50IHNlYXNvbnMuDQoNCiNwb2ludHMgLSBGb3IgaW5zaWdodHMgb24gc2NvcmluZyB0cmVuZHMuDQoNCiNnYW1lX3R5cGUgLSBUbyBkaXN0aW5ndWlzaCBiZXR3ZWVuIHJlZ3VsYXIgc2Vhc29uIGFuZCBwbGF5b2ZmIHBlcmZvcm1hbmNlcy4NCg0KI3dpbl9sb3NlIC0gVG8gY29ycmVsYXRlIEtvYmXigJlzIHBlcmZvcm1hbmNlIHdpdGggdGVhbSBzdWNjZXNzLg0KDQojZmllbGRnb2FsX3BlcmNlbnQgLSBUbyBldmFsdWF0ZSBzaG9vdGluZyBlZmZpY2llbmN5IG92ZXIgdGltZS4NCg0KKiAqICoNCg0KIyBEYXRhIEFuYWx5c2lzDQoNCiMjIFN1bW1hcnkgU3RhdGlzdGljcw0KDQoqVXNpbmcgdGhlIGZhdnN0YXRzKCkgZnVuY3Rpb24sIGNhbGN1bGF0ZSB0aGUgbmVjZXNzYXJ5IHN0YXRpc3RpY3MgeW91IHVzZWQgdG8gY3JlYXRlIHlvdXIgZGF0YSB2aXN1YWxpemF0aW9uLiBEZWxldGUgdGhpcyB3aGVuIGNvbXBsZXRlLioNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBDb252ZXJ0IG5lY2Vzc2FyeSBjb2x1bW5zIHRvIG51bWVyaWMsIGhhbmRsaW5nIG5vbi1udW1lcmljIGVudHJpZXMNCmtvYmVfYnJ5YW50JHBvaW50cyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihrb2JlX2JyeWFudCRwb2ludHMpKQ0KDQojIENhbGN1bGF0ZSBmYXZvcml0ZSBzdGF0aXN0aWNzIGZvciBwb2ludHMNCnBvaW50c19zdGF0cyA8LSBmYXZzdGF0cyh+IHBvaW50cywgZGF0YSA9IGtvYmVfYnJ5YW50KQ0KDQpwcmludChwb2ludHNfc3RhdHMpDQoNCmBgYA0KDQo+IFByb3ZpZGUgdGhlIGhpZ2gtbGV2ZWwgaW5zaWdodHMgeW91IHVzZWQgdG8gY3JhZnQgeW91ciBkYXRhIHZpc3VhbGl6YXRpb24gZGVzaWduLg0KDQojIyBBZGRpdGlvbmFsIEFuYWx5c2VzDQoNCipJZiB5b3UgY29uZHVjdGVkIGFueSBvdGhlciBhbmFseXNlcyBvZiB5b3VyIGRhdGEgc2V0IHRvIGdhdGhlciB0aGUgZGF0YSBpbiB5b3VyIHByb2plY3QsIHVzZSB0aGlzIHNlY3Rpb24gdG8gY29uZHVjdCB5b3VyIHJlc2VhcmNoLiBEZWxldGUgdGhpcyB3aGVuIGNvbXBsZXRlLioNCg0KPiBPcGVuaW5nIFRpbWVsaW5lIG9mIENhcmVlciBIaWdobGlnaHRzDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRwbHlyKQ0KDQoNCiMgQ29udmVydCBmYWN0b3JzIHRvIGNoYXJhY3RlcnMgdG8gZW5zdXJlIHRoZXkgd29yayB3ZWxsIHdpdGggcGxvdGx5DQprb2JlX2JyeWFudCRzZWFzb24gPC0gYXMuY2hhcmFjdGVyKGtvYmVfYnJ5YW50JHNlYXNvbikNCg0KIyBFbnN1cmUgJ3BvaW50cycgaXMgbnVtZXJpYyBmb3IgY2FsY3VsYXRpb25zDQprb2JlX2JyeWFudCRwb2ludHMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoa29iZV9icnlhbnQkcG9pbnRzKSkNCg0KIyBDYWxjdWxhdGUgYXZlcmFnZSBwb2ludHMgcGVyIHNlYXNvbg0KYXZnX3BvaW50c19wZXJfc2Vhc29uIDwtIGtvYmVfYnJ5YW50ICU+JQ0KICBncm91cF9ieShzZWFzb24pICU+JQ0KICBzdW1tYXJpc2UoYXZnX3BvaW50cyA9IG1lYW4ocG9pbnRzLCBuYS5ybSA9IFRSVUUpKQ0KDQojIENyZWF0ZSB0aGUgZ2dwbG90DQpwIDwtIGdncGxvdChhdmdfcG9pbnRzX3Blcl9zZWFzb24sIGFlcyh4ID0gc2Vhc29uLCB5ID0gYXZnX3BvaW50cykpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIktvYmUgQnJ5YW50J3MgQXZlcmFnZSBQb2ludHMgcGVyIFNlYXNvbiIsDQogICAgICAgeCA9ICJTZWFzb24iLA0KICAgICAgIHkgPSAiQXZlcmFnZSBQb2ludHMiKQ0KDQojIENvbnZlcnQgZ2dwbG90IHRvIGFuIGludGVyYWN0aXZlIHBsb3RseSBvYmplY3QNCmludGVyYWN0aXZlX3AgPC0gZ2dwbG90bHkocCkNCg0KIyBQcmludCB0aGUgaW50ZXJhY3RpdmUgcGxvdCB0byB0aGUgVmlld2VyIGluIFJTdHVkaW8gb3IgaW4geW91ciBSIGVudmlyb25tZW50DQpwcmludChpbnRlcmFjdGl2ZV9wKQ0KDQoNCg0KDQoNCmBgYA0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCg0KIyBGaW5kIHRoZSB0b3Agc2NvcmluZyBnYW1lcw0KdG9wX3Njb3JpbmdfZ2FtZXMgPC0ga29iZV9icnlhbnQgJT4lDQogIGFycmFuZ2UoZGVzYyhwb2ludHMpKSAlPiUNCiAgdG9wX24oMTAsIHBvaW50cykNCg0KIyBQbG90DQp0b3BfZ2FtZXNfcGxvdCA8LSBnZ3Bsb3QodG9wX3Njb3JpbmdfZ2FtZXMsIGFlcyh4ID0gcmVvcmRlcihkYXRlLCBwb2ludHMpLCB5ID0gcG9pbnRzKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgU2NvcmluZyBHYW1lcyBvZiBLb2JlIEJyeWFudCdzIENhcmVlciIsDQogICAgICAgeCA9ICJEYXRlIG9mIEdhbWUiLCB5ID0gIlBvaW50cyBTY29yZWQiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIE1ha2UgaW50ZXJhY3RpdmUNCnRvcF9nYW1lc19pbnRlcmFjdGl2ZSA8LSBnZ3Bsb3RseSh0b3BfZ2FtZXNfcGxvdCkNCnRvcF9nYW1lc19pbnRlcmFjdGl2ZQ0KDQoNCg0KDQpgYGANCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQojIENhbGN1bGF0ZSBhdmVyYWdlIHBvaW50cyBwZXIgc2Vhc29uDQpzZWFzb25hbF9wb2ludHMgPC0ga29iZV9icnlhbnQgJT4lDQogIGdyb3VwX2J5KHNlYXNvbikgJT4lDQogIHN1bW1hcmlzZShhdmdfcG9pbnRzID0gbWVhbihwb2ludHMsIG5hLnJtID0gVFJVRSkpDQoNCiMgUGxvdA0Kc2Vhc29uYWxfcG9pbnRzX3Bsb3QgPC0gZ2dwbG90KHNlYXNvbmFsX3BvaW50cywgYWVzKHggPSBzZWFzb24sIHkgPSBhdmdfcG9pbnRzKSkgKw0KICBnZW9tX2xpbmUoKSArDQogIGdlb21fcG9pbnQoKSArDQogIGxhYnModGl0bGUgPSAiU2Vhc29uYWwgU2NvcmluZyBDb25zaXN0ZW5jeSBPdmVyIEtvYmUgQnJ5YW50J3MgQ2FyZWVyIiwNCiAgICAgICB4ID0gIlNlYXNvbiIsIHkgPSAiQXZlcmFnZSBQb2ludHMgcGVyIEdhbWUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIE1ha2UgaW50ZXJhY3RpdmUNCnNlYXNvbmFsX3BvaW50c19pbnRlcmFjdGl2ZSA8LSBnZ3Bsb3RseShzZWFzb25hbF9wb2ludHNfcGxvdCkNCnNlYXNvbmFsX3BvaW50c19pbnRlcmFjdGl2ZQ0KDQoNCg0KDQpgYGANCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQpjbHV0Y2hfcGVyZm9ybWFuY2VzIDwtIGtvYmVfYnJ5YW50ICU+JQ0KICBmaWx0ZXIocG9pbnRfZGlmZmVyZW5jZSA8PSA1LCBtaW51dGVzX3BsYXllZCA+PSAnMDA6NDU6MDAnKSAlPiUNCiAgbXV0YXRlKGZpbmFsX21pbnV0ZXNfcG9pbnRzID0gYXMubnVtZXJpYyhwb2ludHMpKQ0KDQpwbG90X2x5KGNsdXRjaF9wZXJmb3JtYW5jZXMsIHggPSB+c2Vhc29uLCB5ID0gfmZpbmFsX21pbnV0ZXNfcG9pbnRzLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ21hcmtlcnMnKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIktvYmUgQnJ5YW50J3MgQ2x1dGNoIFBlcmZvcm1hbmNlcyIsIHhheGlzID0gbGlzdCh0aXRsZSA9ICJTZWFzb24iKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlBvaW50cyBpbiBGaW5hbCBNaW51dGVzIikpDQoNCg0KDQoNCmBgYA0KDQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQoNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEV4YW1wbGUgZGF0YSBmcmFtZSB3aXRoIG1pbGVzdG9uZXMNCm1pbGVzdG9uZXMgPC0gZGF0YS5mcmFtZSgNCiAgeWVhciA9IGMoMTk5NiwgMjAwMCwgMjAwNiwgMjAxMCwgMjAxNiksDQogIGV2ZW50ID0gYygiTkJBIERlYnV0IiwgIjFzdCBDaGFtcGlvbnNoaXAiLCAiODEgUG9pbnRzIEdhbWUiLCAiNXRoIENoYW1waW9uc2hpcCIsICJSZXRpcmVtZW50IiksDQogIHkgPSByZXAoMSwgNSkgIyBTYW1lIHkgbGV2ZWwgZm9yIGFsbCBwb2ludHMsIHlvdSBjYW4gYWRqdXN0IHRoaXMgZm9yIGJldHRlciBwb3NpdGlvbmluZw0KKQ0KDQojIFBsb3R0aW5nIHRoZSB0aW1lbGluZQ0KbWlsZXN0b25lX3Bsb3QgPC0gZ2dwbG90KG1pbGVzdG9uZXMsIGFlcyh4ID0geWVhciwgeSA9IHksIGxhYmVsID0gZXZlbnQpKSArDQogIGdlb21fbGluZShhZXMoZ3JvdXAgPSAxKSkgKyAjIE9uZSBncm91cCBmb3IgYWxsIHBvaW50cw0KICBnZW9tX3BvaW50KCkgKyAjIEFkZCBwb2ludHMgdG8gdGhlIHRpbWVsaW5lDQogIGdlb21fdGV4dChudWRnZV95ID0gMC4xKSArICMgU2xpZ2h0bHkgbnVkZ2UgdGV4dCBhYm92ZSB0aGUgcG9pbnRzDQogIGxhYnModGl0bGUgPSAiS29iZSBCcnlhbnQncyBDYXJlZXIgTWlsZXN0b25lcyIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIiIpICsgIyBSZW1vdmUgeS1heGlzIGxhYmVsDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLCAjIFJlbW92ZSB5LWF4aXMgbGluZQ0KICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwgIyBSZW1vdmUgeS1heGlzIHRleHQNCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKSAjIFJlbW92ZSB5LWF4aXMgdGlja3MNCg0KIyBNYWtpbmcgaXQgaW50ZXJhY3RpdmUNCmludGVyYWN0aXZlX21pbGVzdG9uZV9wbG90IDwtIGdncGxvdGx5KG1pbGVzdG9uZV9wbG90KQ0KDQojIFNhdmUgdGhlIGludGVyYWN0aXZlIHBsb3QgaWYgbmVlZGVkDQpodG1sd2lkZ2V0czo6c2F2ZVdpZGdldChpbnRlcmFjdGl2ZV9taWxlc3RvbmVfcGxvdCwgIm1pbGVzdG9uZV9wbG90Lmh0bWwiKQ0KDQoNCg0KDQoNCg0KDQoNCg0KYGBgDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGxvdGx5KQ0KDQojIEFzc3VtaW5nICdwb2ludHMnIGFuZCAnb3Bwb25lbnQnIGFyZSBpbiB5b3VyIGRhdGFzZXQgYW5kICdzZWFzb24nIGlzIGluIHRoZSBmb3JtYXQgJ1lZWVktWVknDQpzY29yaW5nX2hlYXRtYXBfZGF0YSA8LSBrb2JlX2JyeWFudCAlPiUNCiAgZ3JvdXBfYnkoc2Vhc29uLCBvcHBvbmVudCkgJT4lDQogIHN1bW1hcmlzZShhdmdfcG9pbnRzID0gbWVhbihwb2ludHMsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQ0KICBhcnJhbmdlKG9wcG9uZW50LCBzZWFzb24pDQoNCnAgPC0gZ2dwbG90KHNjb3JpbmdfaGVhdG1hcF9kYXRhLCBhZXMoeCA9IHNlYXNvbiwgeSA9IHJlb3JkZXIob3Bwb25lbnQsIC1hdmdfcG9pbnRzKSwgZmlsbCA9IGF2Z19wb2ludHMpKSArDQogIGdlb21fdGlsZSgpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIktvYmUgQnJ5YW50J3MgQXZlcmFnZSBQb2ludHMgUGVyIEdhbWUgQWNyb3NzIFNlYXNvbnMiLA0KICAgICAgIHggPSAiU2Vhc29uIiwNCiAgICAgICB5ID0gIk9wcG9uZW50IikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpDQoNCiMgTWFrZSBpdCBpbnRlcmFjdGl2ZQ0KZ2dwbG90bHkocCkNCg0KDQpgYGANCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQojIEhpc3RvZ3JhbSBvZiBLb2JlJ3MgcG9pbnRzDQpwNSA8LSBnZ3Bsb3Qoa29iZV9icnlhbnQsIGFlcyh4ID0gcG9pbnRzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAiYmx1ZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHRpdGxlID0gIktvYmUgQnJ5YW50J3MgQ2FyZWVyIFBvaW50cyBEaXN0cmlidXRpb24iLCB4ID0gIlBvaW50cyIsIHkgPSAiRnJlcXVlbmN5IikNCg0KZ2dwbG90bHkocDUpDQoNCg0KYGBgDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRwbHlyKQ0KDQojIEVuc3VyZSAncG9pbnRzJyBpcyBudW1lcmljDQprb2JlX2JyeWFudCRwb2ludHMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoa29iZV9icnlhbnQkcG9pbnRzKSkNCg0KIyBGaWx0ZXIgZGF0YSBmb3IgZWFybHkgeWVhcnMgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHBvaW50cyBwZXIgc2Vhc29uDQplYXJseV95ZWFycyA8LSBrb2JlX2JyeWFudCAlPiUNCiAgbXV0YXRlKHNlYXNvbiA9IGFzLmNoYXJhY3RlcihzZWFzb24pKSAlPiUgICMgQ29udmVydCBzZWFzb24gdG8gY2hhcmFjdGVyIGlmIGl0J3Mgbm90DQogIGZpbHRlcihzZWFzb24gPD0gIjE5OTktMDAiKSAlPiUNCiAgZ3JvdXBfYnkoc2Vhc29uKSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19wb2ludHMgPSBtZWFuKHBvaW50cywgbmEucm0gPSBUUlVFKSkNCg0KIyBQbG90dGluZw0KcCA8LSBnZ3Bsb3QoZWFybHlfeWVhcnMsIGFlcyh4ID0gc2Vhc29uLCB5ID0gYXZnX3BvaW50cykpICsNCiAgZ2VvbV9saW5lKCkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBsYWJzKHRpdGxlID0gIktvYmUncyBSaXNlIHRvIFN0YXJkb206IFBvaW50cyBQZXIgR2FtZSBpbiBFYXJseSBTZWFzb25zIiwNCiAgICAgICB4ID0gIlNlYXNvbiIsDQogICAgICAgeSA9ICJBdmVyYWdlIFBvaW50cyIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmdncGxvdGx5KHApDQoNCg0KYGBgDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBDb252ZXJ0IGFzc2lzdHMgdG8gbnVtZXJpYw0Ka29iZV9icnlhbnQkYXNzaXN0cyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihrb2JlX2JyeWFudCRhc3Npc3RzKSkNCg0KIyBDcmVhdGUgYSBzdW1tYXJ5IG9mIGF2ZXJhZ2UgYXNzaXN0cyBhZ2FpbnN0IGVhY2ggb3Bwb25lbnQNCmFzc2lzdF9oZWF0bWFwX2RhdGEgPC0ga29iZV9icnlhbnQgJT4lDQogIGdyb3VwX2J5KG9wcG9uZW50KSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19hc3Npc3RzID0gbWVhbihhc3Npc3RzLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgYXJyYW5nZShkZXNjKGF2Z19hc3Npc3RzKSkNCg0KIyBDcmVhdGUgdGhlIGhlYXRtYXANCnAgPC0gZ2dwbG90KGFzc2lzdF9oZWF0bWFwX2RhdGEsIGFlcyh4ID0gcmVvcmRlcihvcHBvbmVudCwgLWF2Z19hc3Npc3RzKSwgeSA9IGF2Z19hc3Npc3RzKSkgKw0KICBnZW9tX3RpbGUoYWVzKGZpbGwgPSBhdmdfYXNzaXN0cykpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIpICsNCiAgbGFicyh0aXRsZSA9ICJLb2JlIEJyeWFudCdzIEF2ZXJhZ2UgQXNzaXN0cyBBZ2FpbnN0IEVhY2ggT3Bwb25lbnQiLA0KICAgICAgIHggPSAiT3Bwb25lbnQiLA0KICAgICAgIHkgPSAiQXZlcmFnZSBBc3Npc3RzIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQ0KDQojIENvbnZlcnQgdG8gaW50ZXJhY3RpdmUgcGxvdA0KaW50ZXJhY3RpdmVfaGVhdG1hcCA8LSBnZ3Bsb3RseShwKQ0KDQojIFNhdmUgdGhlIGludGVyYWN0aXZlIHBsb3QgYXMgSFRNTA0KaHRtbHdpZGdldHM6OnNhdmVXaWRnZXQoaW50ZXJhY3RpdmVfaGVhdG1hcCwgJ2tvYmVfYXNzaXN0c19oZWF0bWFwLmh0bWwnLCBzZWxmY29udGFpbmVkID0gVFJVRSkNCg0KDQoNCg0KDQoNCmBgYA0KKiAqICoNCg0KYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQojIENvbnZlcnQgcG9pbnRzIHRvIG51bWVyaWMgaWYgaXQncyBub3QgYWxyZWFkeQ0Ka29iZV9icnlhbnQkcG9pbnRzIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGtvYmVfYnJ5YW50JHBvaW50cykpDQoNCiMgSWRlbnRpZnkgdGhlIHBlYWsgcGVyZm9ybWFuY2VzDQpwZWFrX3BlcmZvcm1hbmNlcyA8LSBrb2JlX2JyeWFudCAlPiUNCiAgYXJyYW5nZShkZXNjKHBvaW50cykpICU+JQ0KICBzZWxlY3Qoc2Vhc29uLCBkYXRlLCBvcHBvbmVudCwgcG9pbnRzKSAlPiUNCiAgaGVhZChuID0gMTApICMgWW91IGNhbiBjaGFuZ2UgJ24nIHRvIHNlZSBtb3JlIG9yIGZld2VyIHBlcmZvcm1hbmNlcw0KDQojIERpc3BsYXkgdGhlIHRhYmxlDQpwcmludChwZWFrX3BlcmZvcm1hbmNlcykNCmBgYA0KDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBFbnN1cmUgdGhlIG5lY2Vzc2FyeSBjb2x1bW5zIGFyZSBudW1lcmljDQprb2JlX2JyeWFudCRwb2ludHMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoa29iZV9icnlhbnQkcG9pbnRzKSkNCmtvYmVfYnJ5YW50JGFzc2lzdHMgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoa29iZV9icnlhbnQkYXNzaXN0cykpDQprb2JlX2JyeWFudCR0b3RhbF9yZWJvdW5kcyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcihrb2JlX2JyeWFudCR0b3RhbF9yZWJvdW5kcykpDQoNCiMgQ2FsY3VsYXRlIGEgc2ltcGxlICdQZXJmb3JtYW5jZSBTY29yZScgZm9yIGVhY2ggZ2FtZQ0Ka29iZV9icnlhbnQgPC0ga29iZV9icnlhbnQgJT4lDQogIG11dGF0ZShwZXJmb3JtYW5jZV9zY29yZSA9IHBvaW50cyArIGFzc2lzdHMgKyB0b3RhbF9yZWJvdW5kcykNCg0KIyBGaW5kIHRoZSB0b3AgcGVyZm9ybWFuY2VzIGJhc2VkIG9uIHRoaXMgc2NvcmUNCnRvcF9wZXJmb3JtYW5jZXMgPC0ga29iZV9icnlhbnQgJT4lDQogIGFycmFuZ2UoZGVzYyhwZXJmb3JtYW5jZV9zY29yZSkpICU+JQ0KICBzZWxlY3Qoc2Vhc29uLCBkYXRlLCBvcHBvbmVudCwgcG9pbnRzLCBhc3Npc3RzLCB0b3RhbF9yZWJvdW5kcywgcGVyZm9ybWFuY2Vfc2NvcmUpICU+JQ0KICBoZWFkKG4gPSAxMCkgIyBBZGp1c3QgJ24nIHRvIHNob3cgbW9yZSBvciBmZXdlciBwZXJmb3JtYW5jZXMNCg0KIyBEaXNwbGF5IHRoZSB0YWJsZQ0KcHJpbnQodG9wX3BlcmZvcm1hbmNlcykNCg0KYGBgDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmBgYA0KIyBJbnRlcmFjdGl2ZSBQcmVzZW50YXRpb24gb3IgV2Vic2l0ZSBWaXN1YWxpenRpb24NCg0KKk1vZHVsZSAzJ3MgUHJvamVjdCBhbGxvd3Mgc3R1ZGVudHMgdG8gY2hvb3NlIE9ORSBPUFRJT04gYW1vbmcgdGhlIHR3byBvcHRpb25zIHByb3ZpZGVkIGJlbG93LiBZb3Ugc2hvdWxkIGRlbm90ZSB3aGljaCBPTkUgb2YgdGhlIHR3byBvcHRpb25zIHlvdSBwbGFuIHRvIHB1cnN1ZSBhbmQgcHJvdmlkZSBhIGJyaWVmIG92ZXJ2aWV3IG9mIHlvdXIgdmlzaW9uIGZvciB0aGUgcHJvamVjdC4gRGVsZXRlIHRoZSBvdGhlciBvcHRpb25zIHRoYXQgeW91IHdpbGwgbm90IGJlIHB1cnN1aW5nLioNCg0KIyMgT3B0aW9uIDIgfCBJbnRlcmFjdGl2ZSBXZWJzaXRlDQpTdHVkZW50cyB3aWxsIGNyZWF0ZSBhIHdlYnNpdGUgdGhhdCBwcmVzZW50IHRoZWlyIGRhdGEgZmluZGluZ3MgYW5kIHRvcGljIGluIGEgd2Vic2l0ZSB3aGVyZSB1c2VycyBjYW4gZW5nYWdlIHdpdGggdGhlaXIgcGxhdGZvcm0uIFN0dWRlbnRzIG11c3QgaW5jbHVkZSBhIG1pbmltdW0gb2YgNSBwYWdlcyBvZiBhbmFseXNpcywgMSBwYWdlIGZvciB0aGVpciBob21lLCBhbmQgMSBwYWdlIGZvciByZWZlcmVuY2VzL292ZXJ2aWV3LiANCg0KLSBXZWJzaXRlIFNvZnR3YXJlcyBTdHVkZW50cyBhcmUgQWxsb3dlZCB0byBVc2U6DQogICsgR29vZ2xlIFNpdGVzIChGcmVlISkNCiAgDQo+TGluayBvZiBteSB3ZWJwYWdlDQoNCj4gaHR0cHM6Ly9zaXRlcy5nb29nbGUuY29tL3ZpZXcva29iZS1icnlhbnQtaW5zaDUzMDIvaG9tZT9hdXRodXNlcj0wIA0KDQoNCj4gUGFnZSAxOiBLb2JlJ3MgSW5jZXB0aW9uOiBUaGUgTWFraW5nIG9mIGEgTGVnZW5kDQpUaGlzIHBhZ2UgZGVsdmVzIGludG8gdGhlIGZvcm1hdGl2ZSB5ZWFycyBvZiBLb2JlIEJyeWFudCdzIGNhcmVlciwgZXhhbWluaW5nIGhvdyBhIHlvdW5nLCBhbWJpdGlvdXMgYXRobGV0ZSBldm9sdmVkIGludG8gYSBmdXR1cmUgaWNvbiBvZiBiYXNrZXRiYWxsLiBUaHJvdWdoIGludGVyYWN0aXZlIHZpc3VhbGl6YXRpb25zIG9mIGhpcyBlYXJseSBwZXJmb3JtYW5jZSwgdmlzaXRvcnMgY2FuIHRyYWNlIHRoZSBzdGVhZHkgY2xpbWIgb2YgaGlzIHNraWxscyBhbmQgYWNoaWV2ZW1lbnRzLCBzZXR0aW5nIHRoZSBmb3VuZGF0aW9uIGZvciBhIHN0b3JpZWQgY2FyZWVyLg0KDQo+UGFnZSAyOiBEb21pbmFuY2UgaW4gU2NvcmluZw0KSGVyZSB3ZSBleHBsb3JlIEtvYmUncyByZXB1dGF0aW9uIGFzIGEgc2NvcmluZyBwb3dlcmhvdXNlLiBUaGUgZGF0YSB2aXZpZGx5IGlsbHVzdHJhdGVzIGhpcyBhYmlsaXR5IHRvIGNvbnNpc3RlbnRseSByYWNrIHVwIHBvaW50cywgcmVnYXJkbGVzcyBvZiB0aGUgb3Bwb25lbnQgb3Igc2Vhc29uLiBJbnRlcmFjdGl2ZSBjaGFydHMgYWxsb3cgdXNlcnMgdG8gc2VlIGp1c3QgaG93IEtvYmUncyBzY29yaW5nIHByb3dlc3MgbWFkZSBoaW0gb25lIG9mIHRoZSBtb3N0IGZlYXJlZCBvZmZlbnNpdmUgcGxheWVycyBpbiB0aGUgTkJBLg0KDQo+UGFnZSAzOiBLb2JlIC0gQSBUZWFtIE1hbiENCk1vdmluZyBiZXlvbmQgaW5kaXZpZHVhbCBhY2NvbGFkZXMsIHRoaXMgcGFnZSBmb2N1c2VzIG9uIEtvYmUncyBjb250cmlidXRpb25zIHRvIHRlYW0gc3VjY2Vzcy4gV2l0aCB2aXN1YWxpemF0aW9ucyBoaWdobGlnaHRpbmcgaGlzIGFzc2lzdHMgYW5kIHJlYm91bmRzLCB3ZSBjZWxlYnJhdGUgS29iZSBub3QganVzdCBhcyBhIHNjb3JlciwgYnV0IGFzIGEgdHJ1ZSB0ZWFtIHBsYXllciB3aG8gZWxldmF0ZWQgdGhvc2UgYXJvdW5kIGhpbSB0aHJvdWdoIHNlbGZsZXNzIHBsYXkgYW5kIHN0cmF0ZWdpYyBhc3Npc3RzLg0KDQo+UGFnZSA0OiBDbHV0Y2ggU2NvcmluZzogS29iZSdzIFBsYXlvZmYgRG9taW5hbmNlDQpLb2JlJ3MgYWJpbGl0eSB0byBwZXJmb3JtIHVuZGVyIHByZXNzdXJlIGlzIGxlZ2VuZGFyeSwgYW5kIHRoaXMgcGFnZSdzIGludGVyYWN0aXZlIHZpc3VhbGl6YXRpb25zIHNob3djYXNlIGhpcyBlbGV2YXRlZCBnYW1lIGR1cmluZyBwbGF5b2Zmcy4gQnkgZXhhbWluaW5nIGhpcyBjbHV0Y2ggc2NvcmluZyB3aGVuIGl0IG1hdHRlcmVkIG1vc3QsIHRoaXMgcGFnZSBpbGx1c3RyYXRlcyBob3cgS29iZSBiZWNhbWUgc3lub255bW91cyB3aXRoIHRoZSB0ZXJtICdjbHV0Y2gsJyBzb2xpZGlmeWluZyBoaXMgcm9sZSBhcyBhIHBpdm90YWwgcGxheWVyIGluIGNydWNpYWwgbW9tZW50cy4NCg0KPlBhZ2UgNTogS29iZSdzIExlZ2FjeQ0KVGhlIGZpbmFsIHBhZ2UgaXMgYSB0cmlidXRlIHRvIHRoZSBlbmR1cmluZyBsZWdhY3kgb2YgS29iZSBCcnlhbnQuIEl0IGVuY2Fwc3VsYXRlcyBoaXMgY2FyZWVyIHRocm91Z2ggaW50ZXJhY3RpdmUgdGltZWxpbmVzIGFuZCBtaWxlc3RvbmUgY2hhcnRzIHRoYXQgbmFycmF0ZSB0aGUgc3Rvcnkgb2YgYSByZWxlbnRsZXNzIGNvbXBldGl0b3IsIGFuIGluc3BpcmluZyBsZWFkZXIsIGFuZCBhIGN1bHR1cmFsIGljb24gd2hvc2UgaW5mbHVlbmNlIHRyYW5zY2VuZGVkIHRoZSBzcG9ydCBpdHNlbGYuDQoNCj5Gb3IgZWFjaCBwYWdlLCB0aGUgZGF0YSB2aXN1YWxpemF0aW9ucyBub3Qgb25seSBzZXJ2ZSBhcyBldmlkZW5jZSBvZiBLb2JlJ3MgYmFza2V0YmFsbCBwcm93ZXNzIGJ1dCBhbHNvIGFzIG5hcnJhdGl2ZSB0b29scyB0aGF0IGFsbG93IHZpc2l0b3JzIHRvIGVuZ2FnZSB3aXRoIGhpcyBqb3VybmV5IGFuZCB1bmRlcnN0YW5kIHRoZSBkZXB0aCBvZiBoaXMgaW1wYWN0IG9uIHRoZSBzcG9ydC4NCg0KKiAqICoNCg0KIyBSZWZlcmVuY2VzDQoNCktvYmUgQnJ5YW50IFJlZmVyZW5jZXMNCj4iS29iZSBCcnlhbnQgQmlvZ3JhcGh5ICYgRmFjdHMsIiBCaW9ncmFwaHkuY29tLCBhdmFpbGFibGUgYXQgYmlvZ3JhcGh5LmNvbS9hdGhsZXRlcy9rb2JlLWJyeWFudC4NCg0KPiJLb2JlIEJyeWFudCdzIExpZmUsIExha2VycyBDYXJlZXIgJiBMZWdhY3ksIiBMYWtlcnMgTmF0aW9uLCBhdmFpbGFibGUgYXQgbGFrZXJzbmF0aW9uLmNvbS9rb2JlLWJyeWFudC1iaW9ncmFwaHktbGlmZS1sYWtlcnMtY2FyZWVyLWFuZC1sZWdhY3kuDQoNCj4iRXhwbG9yaW5nIEtvYmUgQnJ5YW50J3MgTkJBIEpvdXJuZXksIiBLYWdnbGUgZGF0YXNldCBieSBBbGZyZWQgS29uZG9ybywgYXZhaWxhYmxlIGF0IGthZ2dsZS5jb20vZGF0YXNldHMvYWxmcmVka29uZG9yby9leHBsb3Jpbmcta29iZS1icnlhbnRzLW5iYS1qb3VybmV5Lg0KDQo+VmFyaW91cyBpbWFnZXMgYW5kIGluZm9ybWF0aW9uIHNvdXJjZWQgZnJvbSBHb29nbGUgSW1hZ2VzIGFuZCBNZWRpdW0gRGF0YSBTY2llbmNlIGFydGljbGVzLCB3aXRoIGNyZWRpdHMgZ2l2ZW4gdG8gdGhlIHBob3RvZ3JhcGhlcnMgYW5kIGF1dGhvcnMgd2hlcmUgYXZhaWxhYmxlLg0KDQoqICogKg0KDQojIyBBbGwgZG9uZSENCg0KS25pdCB0aGUgY29tcGxldGVkIFIgTWFya2Rvd24gZmlsZSBhcyBhIEhUTUwgZG9jdW1lbnQgKGNsaWNrIHRoZSAiS25pdCIgYnV0dG9uIGF0IHRoZSB0b3Agb2YgdGhlIHNjcmlwdCBlZGl0b3Igd2luZG93KSBhbmQgdXBsb2FkIGl0IHRvIHRoZSBzdWJtaXNzaW9uIHBvcnRhbCBvbiBDYW52YXMu